﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using LPBToolsLib;


namespace 电子票存档工具
{
    public partial class FUploadEBills : Form
    {
        SQLSerConfig DBServerCFG { get; }
        SQLSerHelper tSQLRun { get; }
        /// <summary>
        /// 程序当前运行的目录
        /// </summary>
        public string currentDirectory { get; private set; }
        /// <summary>
        /// 用于Zip文件解压的临时目录
        /// </summary>
        public const string tempPath = "temp\\";

        public List<string> sEBillsFList { get; } = new List<string>();
        public FUploadEBills(SQLSerConfig DestDBServerCFG)
        {
            InitializeComponent();
            DBServerCFG = DestDBServerCFG;
            tSQLRun = new SQLSerHelper(DBServerCFG);
            currentDirectory = Directory.GetCurrentDirectory() + "\\";
            if (!Directory.Exists(currentDirectory + tempPath))
            {
                Directory.CreateDirectory(currentDirectory + tempPath);
            }
            listBoxEBillsList.Items.Clear();
            sEBillsFList.Clear();
        }

        private void listBoxEBillsList_DragEnter(object sender, DragEventArgs e)
        {
            // 窗体及控件的AllowDrop必须为True
            // 必须增加以下代码，否则DragDrop不能生效
            if ((e.Data != null) && (e.Data.GetDataPresent(DataFormats.FileDrop)))//文件拖放操作。
            {
                e.Effect = DragDropEffects.All;
            }//重要代码：表明是所有类型的数据，比如文件路径
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void listBoxEBillsList_DragDrop(object sender, DragEventArgs e)
        {
            if ((e.Data != null) && (e.Data.GetDataPresent(DataFormats.FileDrop)))//文件拖放操作。
            {
                object Tmp = e.Data.GetData(DataFormats.FileDrop);
                listBoxEBillsList.Items.Clear();
                sEBillsFList.Clear();
                if (Tmp != null)
                {
                    string[] filePaths = (string[])Tmp;
                    if ((filePaths != null) && (filePaths.Length > 0))
                        foreach (string filePath in filePaths)
                        {
                            listBoxEBillsList.Items.Add(Path.GetFileName(filePath));
                            sEBillsFList.Add(filePath);
                        }
                }
            }
        }

        #region ZipFile 解压文件

        /// <summary>
        /// 解压缩
        /// </summary>
        /// <param name="zipFile">zip地址</param>
        /// <param name="strDirectory">解压</param>
        /// <param name="overWrite">是否覆盖已存在文件</param>
        public static void UnZip(string zipFile, string strDirectory, bool overWrite = true)
        {
            if (File.Exists(zipFile))
            {
                string extension = Path.GetExtension(zipFile);
                if (extension.ToUpper().Equals(".ZIP"))
                {                    
                    using (var zip = ZipFile.OpenRead(zipFile))
                    {
                        foreach (var item in zip.Entries)
                        {
                            var fileName = Path.Combine(strDirectory, item.FullName);
                            var fileDir = Path.GetDirectoryName(fileName);

                            if (!Directory.Exists(fileDir))
                            {
                                Directory.CreateDirectory(fileDir);
                            }
                            try
                            {
                                item.ExtractToFile(fileName, overWrite);
                            }
                            catch { }
                        }
                    }
                }
            }
        }
        #endregion

        /// <summary>
        /// 删除目录下所有文件
        /// </summary>
        /// <param name="directoryPath">等待删除的目标目录</param>
        public void delFileInPaht(string directoryPath)
        {
            //string directoryPath = "目录路径";
            if (Directory.Exists(directoryPath))
            {
                string[] filePaths = Directory.GetFiles(directoryPath);
                foreach (string filePath in filePaths)
                {
                    File.Delete(filePath);
                }
            }
        }

        public bool readXML(string sXMLFileName, out string EIid)
        {
            bool iResult = false;
            EIid = "";
            if (File.Exists(sXMLFileName))
            {
                StringBuilder tXMLFileStr = new StringBuilder();
                tXMLFileStr.Append(File.ReadAllText(sXMLFileName));

                // 加载XML文档
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(sXMLFileName);

                // 提取票据编号
                XmlNodeList booksEIid = xmlDoc.GetElementsByTagName("EIid");
                if (booksEIid.Count > 0)
                {
                    EIid = booksEIid[0].InnerText.Trim();

                    if ((EBillsSQLTools.createEBill(DBServerCFG, EIid))
                        && (EBillsSQLTools.updateEBillBlob(DBServerCFG, EIid, "ElecBill", tXMLFileStr.ToString())))
                    {
                        iResult = true;

                        // 获取所有的"book"元素
                        XmlNodeList booksHeader = xmlDoc.GetElementsByTagName("Header");
                        foreach (XmlNode book in booksHeader)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "EIid":
                                        Console.WriteLine($"票据号: {data.InnerText.Trim()}");
                                        break;
                                    case "Version":
                                        Console.WriteLine($"版本: {data.InnerText.Trim()}");
                                        break;
                                    case "EInvoiceTag":
                                        Console.WriteLine($"类型: {data.InnerText.Trim()}");
                                        break;
                                }
                            }
                        }
                        XmlNodeList booksInherentLabel = xmlDoc.GetElementsByTagName("InherentLabel");
                        foreach (XmlNode book in booksInherentLabel)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "InIssuType":
                                        Console.WriteLine($"{data.ChildNodes[1].InnerText.Trim()}: {data.ChildNodes[0].InnerText.Trim()}");

                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "InIssuType", data.ChildNodes[0].InnerText.Trim().Equals("Y") ? "1" : "0");
                                        break;
                                    case "EInvoiceType":
                                        Console.WriteLine($"{data.ChildNodes[1].InnerText.Trim()}: {data.ChildNodes[0].InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "EInvoiceType", data.ChildNodes[0].InnerText.Trim());
                                        break;
                                    case "GeneralOrSpecialVAT":
                                        Console.WriteLine($"{data.ChildNodes[1].InnerText.Trim()}: {data.ChildNodes[0].InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "GeneralOrSpecialVAT", data.ChildNodes[0].InnerText.Trim());
                                        break;
                                    case "TaxpayerType":
                                        Console.WriteLine($"{data.ChildNodes[1].InnerText.Trim()}: {data.ChildNodes[0].InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TaxpayerType", data.ChildNodes[0].InnerText.Trim());
                                        break;
                                }
                            }
                        }
                        // 红字票专有信息
                        XmlNodeList booksRedEInvoice = xmlDoc.GetElementsByTagName("RedEInvoice");
                        foreach (XmlNode book in booksRedEInvoice)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "OriginalInvoiceCode":
                                        Console.WriteLine($"被红冲蓝字数电票号码: {data.ChildNodes[0].InnerText.Trim()}");
                                        break;
                                    case "CreditNoteNumber":
                                        Console.WriteLine($" 红字发票信息确认单编号: {data.ChildNodes[0].InnerText.Trim()}");
                                        break;
                                }
                            }
                        }

                        XmlNodeList booksSellerInformation = xmlDoc.GetElementsByTagName("SellerInformation");
                        foreach (XmlNode book in booksSellerInformation)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "SellerIdNum":
                                        Console.WriteLine($"销方ID: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "SellerIdNum", data.InnerText.Trim());
                                        break;
                                    case "SellerName":
                                        Console.WriteLine($"销方名称: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "SellerName", data.InnerText.Trim());
                                        break;
                                    case "SellerBankName":
                                        Console.WriteLine($"销方开户行: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "SellerBankName", data.InnerText.Trim());
                                        break;
                                    case "SellerBankAccNum":
                                        Console.WriteLine($"销方开户行号: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "SellerBankAccNum", data.InnerText.Trim());
                                        break;
                                }
                            }
                        }

                        XmlNodeList booksBuyerInformation = xmlDoc.GetElementsByTagName("BuyerInformation");
                        foreach (XmlNode book in booksBuyerInformation)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "BuyerIdNum":
                                        Console.WriteLine($"买方ID: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "BuyerIdNum", data.InnerText.Trim());
                                        break;
                                    case "BuyerName":
                                        Console.WriteLine($"买方名称: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "BuyerName", data.InnerText.Trim());
                                        break;
                                }
                            }
                        }

                        XmlNodeList booksIssuTaxSupervisionInfo = xmlDoc.GetElementsByTagName("TaxSupervisionInfo");
                        foreach (XmlNode book in booksIssuTaxSupervisionInfo)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "InvoiceNumber":
                                        Console.WriteLine($"票据号: {data.InnerText.Trim()}");
                                        break;
                                    case "IssueTime":
                                        Console.WriteLine($"开票时间: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "IssueTime", data.InnerText.Trim());
                                        break;
                                    case "TaxBureauCode":
                                        Console.WriteLine($"税务局ID: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TaxBureauCode", data.InnerText.Trim());
                                        break;
                                    case "TaxBureauName":
                                        Console.WriteLine($"税务局名称: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TaxBureauName", data.InnerText.Trim());
                                        break;
                                }
                            }
                        }

                        XmlNodeList booksBasicInformation = xmlDoc.GetElementsByTagName("BasicInformation");
                        foreach (XmlNode book in booksBasicInformation)
                        {
                            XmlNodeList bookData = book.ChildNodes;
                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "TotalAmWithoutTax":
                                        Console.WriteLine($"无税金额: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TotalAmWithoutTax", data.InnerText.Trim());
                                        break;
                                    case "TotalTaxAm":
                                        Console.WriteLine($"税额: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TotalTaxAm", data.InnerText.Trim());
                                        break;
                                    case "TotalTax-includedAmount":
                                        Console.WriteLine($"价税合计: {data.InnerText.Trim()}");
                                        EBillsSQLTools.updateEBill(DBServerCFG, EIid, "TotalAmount", data.InnerText.Trim());
                                        break;
                                    case "TotalTax-includedAmountInChinese":
                                        Console.WriteLine($"价税合计中文: {data.InnerText.Trim()}");
                                        break;
                                }
                            }
                        }
                        XmlNodeList booksIssuItemInformation = xmlDoc.GetElementsByTagName("IssuItemInformation");
                        int booksIssuItemIdx = 0;
                        foreach (XmlNode book in booksIssuItemInformation)
                        {
                            booksIssuItemIdx++;
                            XmlNodeList bookData = book.ChildNodes;
                            Console.WriteLine($"服务项目序号: {booksIssuItemIdx.ToString()}");

                            foreach (XmlNode data in bookData)
                            {
                                switch (data.Name)
                                {
                                    case "ItemName":
                                        Console.WriteLine($"项目名称: {data.InnerText.Trim()}");
                                        break;
                                    case "SpecMod":
                                        Console.WriteLine($"规格型号: {data.InnerText.Trim()}");
                                        break;
                                    case "MeaUnits":
                                        Console.WriteLine($"单位: {data.InnerText.Trim()}");
                                        break;
                                    case "Quantity":
                                        Console.WriteLine($"数量: {data.InnerText.Trim()}");
                                        break;
                                    case "UnPrice":
                                        Console.WriteLine($"无税单价: {data.InnerText.Trim()}");
                                        break;
                                    case "Amount":
                                        Console.WriteLine($"无税金额: {data.InnerText.Trim()}");
                                        break;
                                    case "TaxRate":
                                        Console.WriteLine($"税率: {data.InnerText.Trim()}");
                                        break;
                                    case "ComTaxAm":
                                        Console.WriteLine($"税额: {data.InnerText.Trim()}");
                                        break;
                                }
                            }
                        }
                    }
                }
            }
            return iResult;
        }

        //Thread tUploadThd = null;

        FOnUploadRun tOnUploadRun = null;
        private void buttonUploadEBills_Click(object sender, EventArgs e)
        {
            if (sEBillsFList.Count > 0)
            {
                if (tOnUploadRun == null)
                {

                    tOnUploadRun = new FOnUploadRun();
                    tOnUploadRun.MainRunThd = new Thread(uploadEBills);
                    tOnUploadRun.listBoxEBillsList = listBoxEBillsList;
                    tOnUploadRun.MainRunThd.Start();
                    tOnUploadRun.ShowDialog();
                    //tUploadThd = new Thread(uploadEBills);
                    //tUploadThd.Start();
                }
                else
                {
                    MessageBox.Show("数据上传中，请稍后！", "警告", MessageBoxButtons.OK);
                }                
            }
            else
            {
                MessageBox.Show("请选择要上传的电子票据！", "警告", MessageBoxButtons.OK);
            }
        }

        private void uploadEBills()
        {
            try
            {
                int iSuccess = 0;
                if ((tOnUploadRun!=null)&&(sEBillsFList.Count > 0))
                {
                    for (int i = 0; i < sEBillsFList.Count; i++)
                    {
                        string file = sEBillsFList[i];
                        string sEIid = "";
                        bool iResult = false;
                        if (File.Exists(file))
                        {
                            string extension = Path.GetExtension(file);
                            if (extension.ToUpper().Equals(".ZIP"))
                            {
                                delFileInPaht(currentDirectory + tempPath);
                                UnZip(file, currentDirectory + tempPath);
                                string[] filePaths = Directory.GetFiles(currentDirectory + tempPath);
                                foreach (string filePath in filePaths)
                                    if (Path.GetExtension(filePath).ToUpper().Equals(".XML"))
                                    {
                                        iResult = readXML(filePath, out sEIid);
                                        logRunInfo(iResult, sEIid, filePath);
                                        if (iResult)
                                            iSuccess++;
                                    }
                                delFileInPaht(currentDirectory + tempPath);
                            }
                            else
                            if (extension.ToUpper().Equals(".XML"))
                            {
                                iResult = readXML(file, out sEIid);
                                logRunInfo(iResult, sEIid, file);
                                if (iResult)
                                    iSuccess++;
                            }
                            else
                            {
                                logRunInfo(false, "", file);
                            }
                        }                        
                    }
                    sEBillsFList.Clear();
                    tOnUploadRun.sMutex.WaitOne();
                    try
                    {
                        tOnUploadRun.sRunLog.Add(string.Format("成功上传{0}张电子票据！", iSuccess.ToString()));
                    }
                    finally
                    {
                        tOnUploadRun.sMutex.ReleaseMutex();
                    }
                }
            }
            finally
            {
                tOnUploadRun.MainRunThd = null;
                tOnUploadRun = null;
            }
        }

        private void logRunInfo(bool UploadResult,string sEIid,string sFileName)
        {
            string sInfo = "";
            string sError = "";
            if (tOnUploadRun != null)
            {
                if (UploadResult)
                {
                    sError = "单据编号->" + sEIid;
                }
                else
                {
                    if (string.IsNullOrEmpty(sEIid))
                        sError = "文件格式错误->" + Path.GetFileName(sFileName);
                    else
                        sError = "存在重复记录->" + sEIid;
                }
                sInfo = string.Format("[{0}]{1}:{2}\r\n",
                    DateTime.Now.ToString("HH:mm:ss fff"),
                    UploadResult ? "成功" : "失败",
                    sError
                    );
                tOnUploadRun.sMutex.WaitOne();
                try
                {
                    tOnUploadRun.sRunLog.Add(sInfo);
                    tOnUploadRun.sDeleteFileName.Add(Path.GetFileName(sFileName));
                }
                finally
                {
                    tOnUploadRun.sMutex.ReleaseMutex();
                }
                Thread.Sleep(100);
            }
        }

        //List<string> sRunLog= new List<string>();

        //List<string> sDeleteFileName= new List<string>();

        //Mutex sMutex =new Mutex(false, "FUploadEBills-20240726");
        private void timer1_Tick(object sender, EventArgs e)
        {
           
        }

        private void listBoxEBillsList_DoubleClick(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog()== DialogResult.OK)
            {
                foreach (string filePath in openFileDialog1.FileNames)
                {
                    listBoxEBillsList.Items.Add(Path.GetFileName(filePath));
                    sEBillsFList.Add(filePath);
                }
            }
        }
    }
}
